#include <stdint.h>

#include "../unit.h"
#include "../fe8.h"
#include "../gba_dma.h"


#define HACK 1

/*
SHOW_EXT    显示扩展
    1
        关闭对全彩支持，默认头像显示，然后各种布局重排列

SHOW_8W_ext
        显示8条武器等级

*/
#define SHOW_EXT 1
#define SHOW_8W_ext 1
#define CODE_old 0

/* D:\src\fe8\ida\fe8n4.gba (2005/4/11 0:32:18)
   起始位置(h): 00A72A90, 结束位置(h): 00A72BEF, 长度(h): 00000160 */

extern void show_hack();
extern void show_();

const uint32_t rom00A72A90[] = {
0x2,  //2表示执行一次函数  ,
0x808a6d9,
0x2,  //关闭单位显示?
0x80300d5,
0x2000e, //2000e 一般后面跟着0x0, 禁用屏幕，如果不执行这个，则不是直接黑屏，会有些花屏
0x0,
0x2, //显示面板背景
0x808a73d,
0x2, //未知
0x80048b5,
0x2,  //显示头像，姓名,职业，等级,和单位职业动画
0x808a8fd,
0x5,        //05执行一个外部事件数据指针？,  这个会设置光暗效果，图层1
0x8a728fc,
0x5,     //设置面板名称
0x8a729f0,
0x5, //有关面板名称的
0x8a72a30,
0x5, //未知
0x8a72a80,
#if HACK
//需要在显示屏幕前处理往生成数据
0x2,
show_hack,
#endif
0x1000c, //应该是条件处理
0x0,
0xb,
0x0,
0x2,  //未知
0x808ab99,


0x1000b, //显示屏幕
0x0,

// 0x1000b, //显示屏幕
// 0x0,
0x2000e,  //未知
0x0,
#if HACK
// 0x2,
// show_hack,  //设置显示
0x3,
//0x808a9c9, //设置以前的按键
show_,
0xa000b, //在面板中,一直停在这里?
0x0,
#else
//如果这两个过程都注释了，则执行后退出属性面板
//03 表示设置按键事件
0x3,
0x808a9c9, //按键处理程序,如果为0，则返回程序
//这里的数据会一直循环,直到r0[0xc] 为0
0xa000b, //在面板中,一直停在这里?
0x0,
#endif

0x2000e,
0x0,
0x9,
0x8a728fc,
0x2,
0x808ab41,  //当关闭面板时，执行808ab41函数
0x2,
0x8030109,
0x2,
0x807b4b9,
0x2,
0x80048d9,  //结束
0x0,  //0,0表示结束
0x0,
};

#include "evel.h"

int memcpy4(void*m,void*s,int size){
    uint32_t *d = m;
    uint32_t *sd = s;
    while(size>=0){
        *d++ = *sd++;
        size -= 4;
    }
    return 0;
}

int memset(void*m,uint32_t v,int size){
    uint32_t *mp = m;
    while(size>=0){
        *mp++ = v;
        size -= 4;
    }
    return 0;
}

static int setmap(uint16_t*map,int x,int y,int tile){
    uint32_t m = (uint32_t)map;
    m += y*0x40;
    map = (void*)m;
    map[x] = tile;
}

static int getmap(uint16_t*map,int x,int y){
    uint32_t m = (uint32_t)map;
    m += y*0x40;
    map = (void*)m;
    return map[x];
}

static int fillmap(uint16_t *map,int x,int y,int w,int h,int t){
    int bx = x;
    int endX = x+w;
    int endY = y+h;
    for(;y<endY;y++){
        for(x=bx;x<endX;x++){
            if(x<0x20&&y<0x20){
                setmap(map,x,y,t);
            }
        }
    }
    return 0;
}

//__attribute__((optimize("O3")))
static int movemap(uint16_t*map,int x,int y,int w,int h,int mx,int my){
    uint16_t bak[0x400];
    int zero = 0;
    //memcpy4(bak,map,sizeof(bak));
    gba_memcpy((void*)bak,(void*)map,sizeof(bak));

    int endX = x+w;
    int endY = y+h;
    int bx = x;
    int bmx = mx;
    int by = y;

    //把原图层置为0
    for(;y<endY;y++){
        for(x=bx;x<endX;x++){
            setmap(map,x,y,0);
        }
    }

    y = by;

    for(;y<endY;y++){
        mx = bmx;
        for(x=bx;x<endX;x++,mx++){
            if(x<0x20&&y<0x20){
                int t = getmap(bak,x,y);
                //setmap(map,x,y,0); //设置为空
                if(mx<0x20&&my<0x20){
                    setmap(map,mx,my,t);
                }
            }
            //mx ++;
        }
        my ++;
    }

}

static int switchShow(int a);
uint32_t *const switchData = (void*)0x06006700;
uint32_t *const switchDataB = (void*)0x06006704;
uint32_t *const switchDataChar = (void*)0x0203fff0;
extern void show_hblank();

#define FULLCOLOR_TEST 1
#define USE_IRQ     1
#define HOOK_IRQ    0

typedef struct{
    uint8_t* tile;
    int     size;
    uint8_t* pal;
    uint8_t **_linepal;
}portrait_data_t;

typedef struct{
    int             count;
    int16_t         rev;
    int16_t         status;
    int             line;
    portrait_data_t *portrait;
    u32             *dma;
    u32             *dma2;
    u32             *dma3;
}hook_irq_data;

hook_irq_data * const hook_irq = (void*)0x201fc00;

//#define irqSet(m,f) hook_irqset(m,f)

#if 0
#define color_start 0
#include "hblank.h"
#else
#define color_start 0x80
#define linepal evel_linepal
#define pal     evel_pal
#include "hblank2.h"
#endif
#include "evelfull.h"
#define draw_tile evel_fulldata

#define draw_pal mareeta_pal
#define draw_tile mareeta_tile
#define linepal mareeta_linepal
#include "image.h"

#include "../hack/_140portrait_data.h"

static const portrait_data_t portraits[0x100] = {
    //[2] = {mareeta_tile,sizeof(mareeta_tile),mareeta_pal,mareeta_linepal},
    //[1] = {evel_fulldata,sizeof(eval_tile),evel_pal,evel_linepal}
#if SHOW_EXT==1
#else
    #include "../hack/_140portrait_def.h"
#endif
};


void show_hblank(){
    //int v = REG_VCOUNT;
    (*(int*)0x200f000) ++;
    if(hook_irq->status&0x10){
        //无头像
        return;
    }
    // if(*(int*)0x200f000){
    //     return 0;
    // }
    //使用dma 或者cpucopy
    //dmaCopy32(eval_tile,0x06009d80,18*0x40);
    // if((v&0xf)==15){
    //     gba_memcpy(0x06009d80,eval_tile,18*0x40);
    // }
    int line = REG_VCOUNT;
    hook_irq->count++;
    #if 0
    #define gba_memcpy(d,s,size) DMA_Copy(3,s,d,/*DMA_HBLANK |*/ DMA32 | (size)>>2)
    //此模式
    // mGBA         line += 1
    // nogba 2.7    line += 1
    //       1.4    line += 1
    //vba(nobios&bios)  line += 1

    //需要关闭DMA_HBLANK ，如果不关闭DMA_HBLANK，则不需要line+=1;
    line+=0;
    #define init_line 159
    #elif 0
    #define gba_memcpy(d,s,size) DMA_Copy(3,s,d,/*DMA_HBLANK|*/DMA32 | (size)>>2)
    //需要关闭DMA_HBLANK ，如果不关闭DMA_HBLANK，则不需要line+=1;
    //mGBA      line += 0
    //nogba 1.4 line += 1
    //      2.7 line += 1
    //vba(nobios&bios) line += 0
    line+=0;
    #define init_line 159
    #else
    #define init_line 160
    //此模式
    //nogba1.4      line += 1
    //nogba2.7      line += 1
    //mGBA          line += 0
    //vba(nobios&bios)   line += 0;
    line += 1;
    #endif
    /*
    两个平台的模拟会出现这种情况，大概是因为
        nogba       在执行扫描线时 hblank时，已经绘制完当前扫描线
        mGBA vba    在执行扫描线时 hblank时，还没绘制当前扫描线，执行完hblank，才开始绘制

    如果想修正错误，需要一个dma，设置HBLANK ,在HBLANK中断时，开始copy 下一行调色板，copy完成后，才绘制颜色到lcd


    */
   //hook_irq->count++;
    #if FULLCOLOR_TEST
    line += hook_irq->line;

	// if(line==init_line){
	// 	line = 0;
	// }
    if(line==1){
        line = 0;
    }
    if(line<1){
        line = 0;
    }
	if(line<160){
        if(hook_irq->portrait){
            void *pal_data = hook_irq->portrait->_linepal[line];
            if(pal_data){
                //gba_memcpy(0x05000000+color_start*2,pal_data,0x80*2);
                hook_irq->dma[0] = pal_data;
                hook_irq->dma[1] = 0x05000000+color_start*2;
                hook_irq->dma[2] = /*DMA_HBLANK |*/ DMA_ENABLE|DMA32|((0x80*2)>>2);
            }
        }
	}
    #undef gba_memcpy
    #endif //FULLCOLOR_TEST
    //irqEnable(IRQ_HBLANK); //需要一直开启
}

void show_(uint32_t r0){
    CALLT(0x808a9c8,r0); //按键事件
    #if USE_IRQ
   if(!(*(int*)0x200f000)){
        *(int*)0x200f04 = irqSet(IRQ_HBLANK,show_hblank);
        irqEnable(IRQ_HBLANK);
    }
    irqEnable(IRQ_HBLANK);
    //需要一直开启HBLANK
    //if((*(int*)0x200f000)<0x10000){
        //irqEnable(IRQ_HBLANK);
    //}
    #endif
}

static int switchShow(int a){
    if(a>10){
        a = *(char*)0x02003bfc;
        *switchDataB = 1;
    }
    memset((void*)(0x2022ca8+0x800*3),0,0x600);
    uint16_t *map2 = (void*)(0x2022ca8+0x800*2);

    uint16_t *map0 = (void*)(0x2022ca8+0x800*0); //0x2022cc0

    if(!*switchDataB){
        //把名字，职业，HP移到下方
        movemap(map0,1,10,8,10,0,10+1);
        movemap(map0,1,11,12,2,1,11+1);
        fillmap(map2,0,0,8+4,8+4,0);
    }

    if(a==1){
        //道具面板
        movemap(map2,13,2,16,10,0,2-2);

        //把道具移到左上方
        movemap(map0,13,2,16,11,0,2-2);

        //把道具数量稍微往左移动
        movemap(map0,10,0,6,11,10-2,0);

        //攻击面板
        movemap(map0,13,2+11,16,6,13,2+11+1);
        movemap(map2,13,2+11,16,6,13,2+11+1+4);
    }
    else if(a==0){
        //能力面板

        //把能力移到左上角
        movemap(map0,13,3,16,12,0,2-2);
        movemap(map2,13,3,16,12,0,2-2);
    }
    else if(a==2){
        //武器熟练度面板
        //左侧
        movemap(map0,13,3,8,4,0,2-2);
        //右侧
        movemap(map0,13+8,3,8,4,0+7,2-2);

        //
        movemap(map2,13+1,3,8,4,0,2-2);
        //右侧
        movemap(map2,13+8+1,3,8,4,0+7,2-2);
        //movemap(map2,8,0,8,4,7,2-2);

        //把文本移动一下
        movemap(map0,2,0,2,4,2+1,0);
        movemap(map0,2+7,0,2,4,7+2+1,0);
    }
    *switchData = a;
    return 0;
}

void show_hack(){
    int id = getcurrent_unitId();
    // if(id!=1){
    //     return;
    // }

    if(!portraits[id].tile){
        //无头像
        hook_irq->status |= 0x10;
    }
    else{
        //有头像
        hook_irq->status &= ~0x10;
    }


    if(!portraits[id&0xff].tile){
        return;
    }

        //u8 id = getcurrent_unitId();
    portrait_data_t *portrait = portraits + (id & 0xff);
    #if USE_IRQ
    irqSet(IRQ_HBLANK,show_hblank);
    irqEnable(IRQ_HBLANK);
    #endif

    //测试程序是否执行 0x203f100
    //*(int*)0x02000000 = 0x111111;
    uint16_t *DISPCNT_ptr = (void*)(0x3003020);
    uint16_t *BG0CNT_ptr = (void*)(0x0300302c);
    uint16_t *BG1CNT_ptr = (void*)(0x0300302c+4);
    uint16_t *BG2CNT_ptr = (void*)(0x0300302c+8);
    uint16_t *BG3CNT_ptr = (void*)(0x0300302c+12);

#define DISPCNT (*DISPCNT_ptr)
#define BG0CNT (*BG0CNT_ptr)
#define BG1CNT (*BG1CNT_ptr)
#define BG2CNT (*BG2CNT_ptr)
#define BG3CNT (*BG3CNT_ptr)
    DISPCNT &= ~(1<<13); //禁用窗口0，因为会有竖线

#define SetBG256(v)             v |= (1<<7)
#define SetBG_mapbase(v,b)      (v&~(31<<8))|((b&0x1f)<<8)
#define SetBG_tilebase(v,b)     (v&~(3<<8))|((b&0x3)<<2)

    //设置256色模式
    SetBG256(BG1CNT);
    //SetBG256((*(uint16_t*)0x0400000a));

    //memset((void*)(0x2022ca8+0x800*0),0,0x800); //图层1的显示
    //memset((void*)(0x2022ca8+0x800*2),0,0x800); //显示条形的背景
    memset((void*)(0x2022ca8+0x800*3),0,0x600);
    memset((void*)(0x06007800),0,0x600);
    uint16_t *map2 = (void*)(0x2022ca8+0x800*2);

    {

        uint16_t *map0 = (void*)(0x2022ca8+0x800*0); //0x2022cc0

        // //把名字，职业，HP移到下方
        // movemap(map0,1,10,8,10,0,10+1);
        // movemap(map0,1,11,12,2,1,11+1);
        switchShow(*(char*)0x02003bfc);

        #if 0
        //道具面板

        //把道具移到左上方
        movemap(map0,13,2,16,11,0,2-2);

        //把道具数量稍微往左移动
        movemap(map0,10,0,6,11,10-2,0);

        //攻击面板
        movemap(map0,13,2+11,16,6,13,2+11+1);
        #elif 0
        //能力面板

        //把能力移到左上角
        movemap(map0,13,3,16,12,0,2-2);
        #elif 0



        //武器熟练度面板
        //左侧
        movemap(map0,13,3,8,4,0,2-2);
        //右侧
        movemap(map0,13+8,3,8,4,0+7,2-2);


        fillmap(map2,0,0,8+4,8+4,0);

        //
        movemap(map2,13+1,3,8,4,0,2-2);
        //右侧
        movemap(map2,13+8+1,3,8,4,0+7,2-2);

        //把文本移动一下
        movemap(map0,2,0,2,4,2+1,0);
        movemap(map0,2+7,0,2,4,7+2+1,0);

        #endif
    }

    SetBG_tilebase(BG1CNT,0);
    uint16_t *map1 = (void*)(0x2022ca8+0x800); //0x2022cc0
    #if FULLCOLOR_TEST
    int w = 17;
    #else
    int w = 18;
    #endif
    int x,y;
    #if 0
    int tile = 1248/2;
    uint32_t *p = (void*)0x06009c00;
    #else
    int tile = 630;
    uint32_t *p = (void*)0x06009d80;
    #endif
    int showx = 100/8;
    int showy = 0;
    for(y=0;y<32;y++){
        for(x=0;x<32;x++){
            int ax = x-showx;
            if(ax>=0&&ax<w&&y<18){
                setmap(map1,x,y,y*w+ax+tile);
            }
            else{
                setmap(map1,x,y,tile);
            }
        }
    }

    //调色板,从5号调色板开始
    //memcpy4(0x20228c8-0x20 + 0x20 *5,eval_pal,sizeof(eval_pal)-0x20*5);
    *(uint16_t*)(0x20228c8-0x20) = 0;
    #if FULLCOLOR_TEST
    //gba_memcpy((void*)0x06009d80,draw_tile,sizeof(draw_tile));
    gba_memcpy((void*)0x06009d80,portrait->tile,portrait->size);
    hook_irq->portrait = portrait;
    hook_irq->dma = &REG_DMA3SAD;
    #elif 0
    memcpy4((void*)0x06000000,eval_tile,sizeof(eval_tile));
    #else
    //因为从5号调色板开始，所以
    int offset;
    uint32_t v=0;
    for(offset=0;offset<sizeof(eval_tile);offset++){
        if(((offset&3)==0)&& (*(uint32_t*)&eval_tile[offset]==0)){
            *p++ = 0;
            offset += 3;
        }
        else{
            int pixel = eval_tile[offset];
            if(pixel ){
                pixel  += + 5*0x10;
            }
            v |= ((pixel)&0xff)<<((offset&0x3)*8);
            if((offset&3)==3){
                *p++ = v;
                v = 0;
            }
        }
    }
    #endif

    //memset((void*)(0x20244c0),0,0x800);
    //memset(0x06007800,0,0x800)
}


void JMP808ABD8_r2(uint32_t r0,uint32_t r1){
    uint32_t r2 = 0x2003BFC;
    strh(r2+4,0);
    strh(r2+6,0);

    uint8_t r4 = getb(0x202bcec+0x14);
    strb(r2,r4&3);
    str(r2+0xc,r0);
    str(r2+0x14,0);
    strh(r2+2,0);
    strb(r2+8,0);
    CALLT(0x80A91D0,getb(get(r0)+4));

    if(!(getb(0x202BCEC+0x41)&2)){
        //0x202BCEC为选择的角色数据
        CALLT(0x80D4EF4,106);
    }
    //8A72A90为游戏事件调用的数据指针
    #if 0
    CALLT(0x8002C30,0x8A72A90,r1);
    #else
    *switchDataChar = r1;
    CALLT(0x8002C30,rom00A72A90,r1);
    //返回值是 0202515c
    //数据结构参考08003308
    #endif
}

//切换面板时执行
void _8089C68_hack(uint32_t r0){

    /*


    */

    uint8_t id = getcurrent_unitId();
    if(portraits[id].tile==0){
        CALLT(0x8089C68,r0);
        return;
    }
    uint16_t *map0 = (void*)(0x2022ca8+0x800*0); //0x2022cc0
    uint16_t *map2 = (void*)(0x2022ca8+0x800*2); //
    fillmap(map0,0,0,12,12,0);
    fillmap(map2,0,0,12,12,0);
    CALLT(0x8089C68,r0);
    switchShow(20);
}

const uint32_t rom8A728E4[] = {
    #if HACK
    3, _8089C68_hack,
    #else
    3, 0x8089C69,
    #endif
    2, 0x8089D59,
    0,0, //结束
};


/*
0x2003bfc
    保存人物面板页的索引
0x2003bfd
    属性页的页数,包括显示面板页的页数
*/
//r1 为属性面板页索引
void JMP8089D64_r3(uint16_t r0,uint16_t r1,uint32_t r2){
    if(!CALLT(0x8002DEC,rom8A728E4)){
        if(!(*(char*)(0x202BCEC+0x1e)&2)){
            CALLT(0x80d4ef4,111);
        }
        uint32_t v6 = CALLT(0x8002C30,rom8A728E4,r2) + 0x4c;
        *(short*)v6 = 0;
        v6 -= 2;
        *(short*)v6 = r1;       //面板切换时的索引
        *(short*)(v6+8) = r0;
        *(short*)(0x2003BFC+2) = r0;
        *(int*)(0x2003BFC+0x14) = 0;
        *(char*)(0x2003BFC+0x8) = 1;
    }
}

uint32_t _808AAA8hack(uint32_t r0,uint32_t r1){

    CALLT(0x808a73c,r1); //重新设置背景

    if(r0){
        return CALLT(0x8089BAC,*(uint32_t*)(0x2003BFC+0xc),1);
    }
    else{
        return CALLT(0x8089BAC,*(uint32_t*)(0x2003BFC+0xc),-1);
    }
}

void _808AAA8(){

    asm("mov r0,r0");
    asm("JMP808AAA8_r0:\n");

    asm("mov r0,#0\n");
    asm("mov r1,r5\n");
    asm("mov r4,#1\n");
    asm("neg r4,r4\n");
    asm("bl _808AAA8hack\n");

    asm("ldr r1,_0x808AAB6R\n");
    asm("bx r1\n");
    asm(".align 4\n");
    asm("_0x808AAB6R:.int 0x808AAB6+1");
}

void _808AAC8(){

    asm("mov r0,r0");
    asm("JMP808AAC8_r0:\n");

    asm("mov r0,#1\n");
    asm("mov r1,r5\n");
    asm("bl _808AAA8hack\n");

    asm("ldr r1,_0x808Aad2R\n");
    asm("bx r1\n");
    asm(".align 4\n");
    asm("_0x808Aad2R:.int 0x808Aad2+1");
}

static void setTile(){

}

const uint32_t rom8A7291C[] = {
    0xE, 0,
    2, 0x8089E91,

    2, 0x8089EC1,
    3, 0x8089F4D,
    2, 0x808A085,
    2,show_hack,
    2, 0x8089FB1,
    3, 0x808A025,
    0xE, 0,
    2, 0x8089E7D,
    2, 0x808A0B5,

    0, 0,
};

//在属性面板，人物切换时
void JMP808A108_r3(uint32_t r0,uint32_t r1,uint32_t r2){
    uint32_t v5 = //CALLT(0x8002C30,0x8A7291C,r2);
        CALLT(0x8002C30,rom8A7291C,r2);
    *(short*)(v5+0x4a) = *(uint8_t*)(r0+11);
    *(uint32_t*)(v5+0x38) = r1;
    if(!(*(uint8_t*)(0x202BCEC+0x41)&0x2)){
        CALLT(0x80D4EF4,200);
    }
    *(int32_t*)0x203fff0 = r2;

}


//////////////////////////////////////////////////////////
//设置中断程序
#if HOOK_IRQ

uint32_t IRQ_call(uint32_t r0,uint32_t irq_idx,uint32_t regv){
    //hook_irq->rev = irq_idx;
    // if(regv){
    //     hook_irq->rev = regv;
    // }
    //hook_irq->count ++;
    if(hook_irq->fn[irq_idx>>2]){
        hook_irq->rev = r0;
        hook_irq->fn[irq_idx>>2]();
    }
    return r0;
}

void _80001E0_r0(){
    asm("mov r1,r1\n");
    asm(".arm\n");
    asm("AJMP80001E0_r0:\n");
    asm("mov r1,r1\n");
    asm("AJMP30041e4_r0:\n");
    asm("mov r3,r1\n");
    asm("ldr r1,=0x3003090\n");
    asm("add r1,r1,r2\n");
    asm("ldr r0,[r1]\n");
    asm("stmfd sp!,{lr}\n");
    #if !HACK_NIRQ
    asm("mov r1,r2\n");
    asm("mov r2,r3\n");
    asm("bl IRQ_call\n");
    #endif

    asm("add lr,pc,#0\n");
    asm("bx r0\n");
    asm("ldr lr,=0x30041fc\n");
    asm("bx lr\n");
    asm(".thumb");
}


#endif

///////////////////////////////////////////////////////
//设置显示对话的头像修改

/*
8005544 函数作为设置对话显示的游戏事件函数

8000494 查看精灵数据定义
*/

#if SHOW_8W_ext

/*
设置显示文字
*/


/*
 数据1的地址
 * */
#include "../gba_hack.h"

#include "m8A727B4.h"
//显示帮助
#include "show_help.h"

extern const	tm8A727B4	m8A727B4[];
__attribute__ ((section(".""0x080890B8")))
const u32 m080890B8 = (u32)m8A727B4;

#include "m80890BC.h"

//武器经验条的偏移量，默认是3，隔开一个空位
HACK_DATA(0x8089A70)
const u32 _08089a70 = 0x19a43400 + 2;

static void show_support();

void JMP8089AC4_r1(){
    u32 v0 = 0;
    #if 0
    //原ROM的

    if(CALLT(0x801876C,0x2003C08)||1)
    {
        //杖,光，理，暗
        CALLT(0x80890BC,0x81F548C);     //显示帮助
        CALLT(0x8089A00,0, 1, 1, 5);
        CALLT(0x8089A00,1, 1, 3, 6);
        CALLT(0x8089A00,2, 9, 1, 7);
        v0 = CALLT(0x8089A00,3, 9, 3, 4);
        }
    else
    {
        //剑，枪...
        CALLT(0x80890BC,0x81F543C);     //显示帮助
        CALLT(0x8089A00,0, 1, 1, 0);
        CALLT(0x8089A00,1, 1, 3, 1);
        CALLT(0x8089A00,2, 9, 1, 2);
        v0 = CALLT(0x8089A00,3, 9, 3, 3); //显示支援?
    }
    #else

    //剑，枪...
    //CALLT(0x80890BC,0x81F543C);     //显示文字
    CALLT(0x80890BC,m80890BC);      //显示文字
    CALLT(0x8089A00,
    0,      //写入图层的索引,如果有重复,则会覆盖图层?
    1,      //坐标X
    1,      //坐标Y
    0       //图标X:  -------
    );
    CALLT(0x8089A00,1, 1, 3, 1);
    CALLT(0x8089A00,2, 1, 1+4, 2);
    CALLT(0x8089A00,3, 1, 3+4, 3);

    //杖,光，理，暗
    //CALLT(0x80890BC,0x81F548C);     //显示帮助
    CALLT(0x8089A00,3, 1, 1+8, 5);
    CALLT(0x8089A00,4, 1, 3+8, 6);
    CALLT(0x8089A00,5, 1, 1+8+4, 7);
    v0 = CALLT(0x8089A00,3, 1, 3+8+4, 4);
    #endif
    #if !CODE_old
    //显示支援
    //CALLT(0x8089910,v0);
    //show_support();
    //显示八项武器，再调用熟练度，会出现bug
    #endif
}

void _808941C(){
    CALLT(0x808941C);
}

void _80896EC(){
    CALLT(0x80896EC);
}

void _TEST_FUNC(){
    //测试
    //测试绘制一个武器熟练度
    //CALLT(0x8089A00,3, 1, 1+8, 5);
    int x = 1;
    int y = 9;
    CALLT(
        0x8003608,
        2*(0x20*y+x) + 0x2003D2C,   //图层位置
        0 + 0x70,                   //图标索引
        0x4000                      //调色板
    );
}

static
void _808941C_r2_2();
static void show_growth();

//属性页的最大页数
SET_DATA(0x808A91C)
const u32 _808A91C = 0x70682000+5;

#if 0
//808A3FC
SET_DATA(0x808A3FC)
const u32 _808A3FC =
    //0xF7FF7820;   //ldrb r0,[r4]      bl sub_808A144
    0xF7FF2001;     //mov r0,#1         bl sub_808A144

//808A3FC   正在显示时，不出bug,切换时，出bug，卡在正中间
//808A410   如果已经正在显示，则不会出bug,切换时，出bug
//808A294,  如果已经正在显示, 则出bug

#else

void LONGJMP_80052F0(int a1, int16_t a2, u8 a3, int a4, int16_t a5);

void _80052F0LONGJMP(){
    asm("mov r0,r0\n");
    asm("JMP_r5:");
    asm("bx r5\n");
    asm("LONGJMP_80052F0:\n");
    asm("push {r5,lr}\n");
    asm("ldr r5,J80052F0\n");
    asm("bl JMP_r5\n");
    asm("pop {r5}\n");
    asm("pop {r1}\n");
    asm("bx r1\n");
    asm(".align 4\n");
    asm("J80052F0: .int 0x80052F0+1");
}

void _80052F0_emu(int a1,s16 a2,u8 a3,int a4,s16 a5){
    #define v3004910 get(0x3004910)
    int v6 = 0x10*a1 + 0x202A588;
    int v5 = v3004910;
    str(v3004910,get(v6));
    strh(v5+4,a2 &0x1ff);
    strh(v5+6,a3);
    strh(v5+8,a5);
    str(v5+12,a4);
    str(v6,v5);
    str(0x3004910,v5+16);
}

//需要修改函数代码
void JMP808A144_r1(int a1){
    if(a1>2){
        //大于3，则不更新OAM
        return ;
    }
        // LONGJMP_80052F0(
        // LONGJMP_80052F0(
    //CALLT(0x80052F0,
    _80052F0_emu(
    4,
    (int16_t)geth(0x2003BFC+4)+0x6f,
    (int16_t)geth(0x2003BFC+6)+1,
    0x8A729B6,
    0x4E93);


    CALLT(0x80052F0,
    //_80052F0_emu(
    4,
    (int16_t)geth(0x2003BFC+4)+0x72,
    (int16_t)geth(0x2003BFC+6)+0,
    get(a1*4 + 0x8A729DC),
    geth(0x8A729E8+a1*2)+0x3E40
    );

    // (int16_t)geth(0x2003c00)+0x72,(int16_t)geth(0x2003c02),0x8A729DC+a1*4, geth(0x8A729E8+a1*2)+0x3E40);



    int v2 = CALLT(0X8000CD8);
    //CALLT(0x80D6370,
    CpuSet(
    0x8A748B4+
    0x20*a1+
    2 * (((unsigned int)v2 >> 2) & 0xF),
    0x2022b24,1);
    // str(0x2022B24,
    // get(
    // 0x8A748B4+
    // 0x20*a1+
    // 2 * (((unsigned int)v2 >> 2) & 0xF))
    // );
    CALLT(0x8001EE4);
}
#endif

static void show_support_ex(int x_offset,int y_offset);
static void show_support_mono(){
    show_support_ex(-8,0);
}

void JMP8089B58_r2(int a1){
    callT func[] = {
        #if 0
        0x808941C+1,
        0x80896EC+1,
        0x8089AC4+1,        //显示武器
        0x80896EC+1,
        0x8089AC4+1,
        0x808941C+1,
        #endif
        _808941C,           //显示基本能力
        _80896EC,           //显示道具
        JMP8089AC4_r1,      //显示武器
        _808941C_r2_2,      //基本能力2
        #if 0
        //成长率
        show_growth,
        #else
        //支援等级
        show_support_mono,
        #endif
        _808941C,           //显示基本能力
        _808941C,           //显示基本能力
    };
    // if(a1>3){
    //     strb(0x2003bfc,0);
    // }

    #if !CODE_old
        //清空vram的tile数据，然后菜单对应的map属性，不会被因为vram被覆盖而显示花屏
        //gba_memset(0x06001000,0,0x1800);
        gba_memset(0x06001400,0,0x1800-0x400); //0x06001000 显示名字和职业信息了
    #endif
    int v = 0;
    CALLT(0x80D636C,&v,0x2003D2C, 0x1000140);
    CALLT(0x80D636C,&v,0x200472C, 0x1000120);
    func[a1]();
}

#include "../include/unit.h"

//使用图标
static const u32 icon_data[0x300] = {
#include "../hack/icon_data.h"
};

//绘制图标的程序，这个函数修改指针，已获得扩展的绘图
u32 JMP800359C_r2(int r0){
    //不能超过一些限制
    u32 v2 = 4*r0 + 0x2026A90; //存储着图标绘制的图标位置
    if(getb(v2+1)){
        //存在 //计数?
        if(getb(v2)<=0xfe){
            strb(v2,getb(v2)+1);
        }
    }
    else{
        strb(v2,getb(v2)+1);
        strb(v2+1,
        CALLT(0x8003570,r0)+1
        );
        u32 v4 = CALLT(0x800355C,getb(v2+1));
        #if CODE_old
        //原程序
            //把图标数据复制到目标位置
        CALLT(0x8001F64,0x85BA470+128*(r0),(0x20*v4 & 0x1ffe0)+0x06000000,0x80);
        #else
        u32 data = 0x85BA470+128*(r0);
        if(icon_data[r0]){
            //如果存在替换的图标数据，则设置替换的图标数据
            data = icon_data[r0];
        }
        CALLT(0x8001F64,data,(0x20*v4 & 0x1ffe0)+0x06000000,0x80);
        #endif
    }
    return (u16)CALLT(0x800355C,getb(v2+1));
}

//get(0x2003BFC+0xc)
#define v2003C08 *((u32*)(0x2003BFC+0xc))
static void _808941c_proc2(){
    u8  buf[0x50];
    if((getb(v2003C08+0x30)&0xf)==10){
        CALLT(0x80D6908,
        buf,
        v2003C08,
        0x48
        );
        strb(buf+0x30,getb(buf+0x30)&0xf0);
        CALLT(0x80043B8,0x2003C84, 24, 2,
        CALLT(0x80190EC,buf)
        );
    }
    else{
        CALLT(0x80043B8,0x2003C84, 24, 2,
        CALLT(0x80190EC,v2003C08)
        );
        if(getb(v2003C08+0x30)&0xf){
            CALLT(0x8004AEC,
            0x200400C, 0, getb(v2003C08+0x30) >> 4
            );
        }
    }
}


static
const u32 base_info[] = {
 0x2003C34, 0x2003DEE + 0x20*4 , 3, 0x8A73224,
 0x2003C3C, 0x2003E6E + 0x20*4 ,  3, 0x8A73228,
 0x2003C44, 0x2003EEE + 0x20*4 , 3, 0x8A73234,
 0x2003C4C ,0x2003F6E + 0x20*4 , 3, 0x8A7322C,
 0x2003C54, 0x2003FEE + 0x20*4 , 3, 0x8A73230,

// 0x2003C5C, 0x2003D7E, 3, 0x8A73240,
// 0x2003C64, 0x2003DFE,3, 0x8A73238,
// 0x2003C6C, 0x2003E7E, 3, 0x8A7323C,
// 0x2003C74,0x2003EFE, 3, 0x8A73244,
// 0x2003C7C, 0x2003F7E, 3, 0x8A73248,
// 0x2003C84, 0x2003FFE, 3, 0x8A73260,
0, 0, 0, 0
};

static
const u32 base_info2[] = {
0x2003C5C, 0x2003D7E - 2*8, 3, 0x8A73240,
0x2003C64, 0x2003DFE - 2*8,3, 0x8A73238,
0x2003C6C, 0x2003E7E - 2*8, 3, 0x8A7323C,
0x2003C74, 0x2003EFE - 2*8, 3, 0x8A73244,
0x2003C7C, 0x2003F7E - 2*8, 3, 0x8A73248,
0x2003C84, 0x2003FFE - 2*8, 3, 0x8A73260,
0, 0, 0, 0
};

static int magic_bonus(HackUnit*unit){
    return 0;
}

#define show_value_bar(idx,x,y,value,v0,v1)   \
    CALLT(0x8089354,idx,x,y,value,v0,v1)

#if !CODE_old
static
void _808941C_r2_2(){
    int xoffset = -8;
    int v11 = 0;
    CALLT(0x80890BC,base_info2);
    show_value_bar(6,13+xoffset,1,
    //getb(v2003C08+0x18),
    (v11 = getb(get(v2003C08+4)+0x12))  //获得职业移动
    ,
    getb(v2003C08+0x1d)+v11,            //包括奖励移动
    15 //最大值
    );

    show_value_bar(7,13+xoffset,3,
    (v11=getb(get(v2003C08+4)+0x11) + getb(get(v2003C08)+0x13)),
    v11+getb(v2003C08+0x1a),
    getb(get(v2003C08+4)+0x19) //最大体格
    );

    //救出
    CALLT(0x8004A9C,0x2003E86 - 2*8, 2, CALLT(
        0x80186CC,0x2003C08
    ));

    //显示职业种类?
    CALLT(0x8003608,
    0x2003E88 - 2*8,
    CALLT(0x8018804,
    get(get(v2003C08)+0x28)         //角色能力
    |get(get(v2003C08+4) + 0x28)    //职业能力
    )
    ,0x5000
    );

    //同行
    CALLT(0x80043B8,
    0x2003C74, 24, 2,
    CALLT(0x80190C0,v2003C08)
    );


    #if 0
    u8  buf[0x50];
    if((getb(v2003C08+0x30)&0xf)==10){
        CALLT(0x80D6908,
        buf,
        v2003C08,
        0x48
        );
        strb(buf+0x30,getb(buf+0x30)&0xf0);
        CALLT(0x80043B8,0x2003C84, 24, 2,
        CALLT(0x80190EC,buf)
        );
    }
    else{
        CALLT(0x80043B8,0x2003C84, 24, 2,
        CALLT(0x80190EC,v2003C08)
        );
        if(getb(v2003C08+0x30)&0xf){
            CALLT(0x8004AEC,
            0x200400C, 0, getb(v2003C08+0x30) >> 4
            );
        }
    }
    #else
    //状态
    _808941c_proc2();
    #endif


    //人物属性图标
    CALLT(0x8003608,
    0x2003F84 - 2*8,
    CALLT(0x8028650,v2003C08)
    , 20480
    );


    CALLT(0x8089268,
    CALLT(0x80043B8,
    0x2003C7C, 40, 2,
    CALLT(0x80286A4,
    getb(get(v2003C08)+9) //人物属性
    )
    )
    );
}
#endif

//修改基础属性显示
void JMP808941C_r2(){
    //CALLT(0x80890BC,(int)0x81F531C);    //显示基本的文字
    CALLT(0x80890BC,base_info);
    #if CODE_old
    if (CALLT(0x801876C,v2003C08)){
        CALLT(0x8004374,0x2003C2C, 0x2003D6E, 3, 0, 0, CALLT(0x8009FA8,0x48E));
    }
    else{
        CALLT(0x8004374,0x2003C2C, 0x2003D6E, 3, 0, 0, CALLT(0x8009FA8,0x48D));
    }
    #else
    //strh(0x2003C7c,0);
    /*

    2003C2C 数据结构
        [+0]    非0，   则已经初始化
        [+2]    参数3   小偏移
        [+3]    参数4   未知

    */
    CALLT(0x8004374,0x2003C2C, 0x2003D6E, 3, 0, 3, CALLT(0x8009FA8,0x48D));
    CALLT(0x8004374,0x2003C7C, 0x2003DEE, 3, 0, 3, CALLT(0x8009FA8,0x48E));
    #endif

    //return 0;

    #if CODE_old
    int yoffset = 0;
    #else
    int yoffset = 2;
    #endif

    //攻击力
    show_value_bar(0,5,1,
    getb(v2003C08 + 0x14),
    CALLT(0x8018EC4,v2003C08),
    getb(get(v2003C08+4)+0x14)
    );

    #if !CODE_old
    HackUnit *unit = v2003C08;
    show_value_bar(
    6           //使用体格的索引, 如果使用0，则会占用力量的位置，这时，条形图是共用一个
    ,5,3,
    //getb(v2003C08 + 0x14)
    unit->magic
    ,
    //CALLT(0x8018EC4,v2003C08),
    magic_bonus(unit),
    getb(get(v2003C08+4)+0x14)
    );
    #endif

    int v1_1 = CALLT(0x8018EE4,v2003C08);
    int v1_2 = getb(v2003C08+0x15);
    int v1_3 = getb(get(v2003C08+0x4)+0x15);

    int v2_1 = CALLT(0x8018F24,v2003C08);
    int v2_2 = getb(v2003C08+0x16);
    int v2_3 = getb(get(v2003C08+0x4)+0x16);
    if(get(v2003C08+0xc)&0x10){
        v1_2 = (char)v1_2 + (v1_2<<24>>31)>>1;
        v1_3 = (char)v1_3 + (v1_2<<24>>31)>>1;

        v2_2 = (char)v2_2 + (v1_2<<24>>31)>>1;
        v2_3 = (char)v2_3 + (v1_2<<24>>31)>>1;
    }

    show_value_bar(1,5,3+yoffset,v1_2,v1_1,v1_3); //技术
    show_value_bar(2,5,5+yoffset,v2_2,v2_1,v2_3); //速度

    show_value_bar(3,5,7+yoffset,
    getb(v2003C08+0x19),
    CALLT(0x8018FAC,v2003C08),30
    );

    show_value_bar(4,5,9+yoffset,
    getb(v2003C08+0x17),
    CALLT(0x8018F64,v2003C08),
    getb(get(v2003C08+4)+0x17)
    );

    show_value_bar(5,5,11+yoffset,
    getb(v2003C08+0x18),
    CALLT(0x8018F84,v2003C08),
    getb(get(v2003C08+4)+0x18)
    );

    #if CODE_old
    int v11 = 0;
    show_value_bar(6,13,1,
    //getb(v2003C08+0x18),
    (v11 = getb(get(v2003C08+4)+0x12))  //获得职业移动
    ,
    getb(v2003C08+0x1d)+v11,            //包括奖励移动
    15 //最大值
    );

    show_value_bar(7,13,3,
    (v11=getb(get(v2003C08+4)+0x11) + getb(get(v2003C08)+0x13)),
    v11+getb(v2003C08+0x1a),
    getb(get(v2003C08+4)+0x19) //最大体格
    );

    //救出
    CALLT(0x8004A9C,0x2003E86, 2, CALLT(
        0x80186CC,0x2003C08
    ));

    //显示职业种类?
    CALLT(0x8003608,
    0x2003E88,
    CALLT(0x8018804,
    get(get(v2003C08)+0x28)         //角色能力
    |get(get(v2003C08+4) + 0x28)    //职业能力
    )
    ,0x5000
    );

    //同行
    CALLT(0x80043B8,
    0x2003C74, 24, 2,
    CALLT(0x80190C0,v2003C08)
    );


    #if 0
    u8  buf[0x50];
    if((getb(v2003C08+0x30)&0xf)==10){
        CALLT(0x80D6908,
        buf,
        v2003C08,
        0x48
        );
        strb(buf+0x30,getb(buf+0x30)&0xf0);
        CALLT(0x80043B8,0x2003C84, 24, 2,
        CALLT(0x80190EC,buf)
        );
    }
    else{
        CALLT(0x80043B8,0x2003C84, 24, 2,
        CALLT(0x80190EC,v2003C08)
        );
        if(getb(v2003C08+0x30)&0xf){
            CALLT(0x8004AEC,
            0x200400C, 0, getb(v2003C08+0x30) >> 4
            );
        }
    }
    #else
    //状态
    _808941c_proc2();
    #endif


    //人物属性图标
    CALLT(0x8003608,
    0x2003F84,
    CALLT(0x8028650,v2003C08)
    , 20480
    );


    CALLT(0x8089268,
    CALLT(0x80043B8,
    0x2003C7C, 40, 2,
    CALLT(0x80286A4,
    getb(get(v2003C08)+9) //人物属性
    )
    )
    );
    #endif

}


#if !CODE_old

void _8089354ex(int idx, int x, int y, int value, signed int value_bonus, int maxValue,int show_num){
    u32 show_tile = 2;
    u16 *map = (u16*)((2*(0x20*y+x)) + 0x2003d2c);
    if(value==maxValue){
        show_tile = 4;
    }
    if(show_num<0){
        CALLT(0x8004A9C,map,show_tile,value);
    }
    else{
        CALLT(0x8004A9C,map,show_tile,show_num);
    }

    CALLT(0x8004AF8,
        value_bonus - value,
        2*(y*0x20 + 1 + x)
    );

    int show_len = value_bonus - value;
    if(maxValue>30){
        show_len = 30 - value;
    }

    int v1 = CALLT(0x80D65F8,0x29*maxValue,0x1e);
    int v2 =  CALLT(0x80D65F8,0x29*value,0x1e);
    int v3 = CALLT(0x80D65F8,0x29*show_len,0x1e);
    CALLT(0x8088DE8,
    6*idx+0x401,6,
    2*(0x20*(y+1)-2+x)+0x200472C,
    0x6000,
    v1,v2,v3
    );
}

extern u8 magic_growth[0x100] = {
    [0 ... 0xff] = 5,
};

static u8 char_get_magic_growth(u8 id){
    return magic_growth[id];
}

/*
显示支援
*/

static void show_support_ex(int x_offset,int y_offset);
static void show_support(){
    show_support_ex(0,0);
}

static void show_support_ex(int x_offset,int y_offset){
//#define v2003C08 *(int*)(0x2003C08)
    int v1 = 0;
    if(CALLT(0x80281f8,v2003C08)==5){
        v1 = 4;
    }
    int v2 = CALLT(0x802815C,v2003C08);
    int v3 = 0;
    int value = 6;
    #if CODE_old
    int     y   =       0;
    int yoffset =       0;
    int xoffset =       0;
    int name_offset = 0;
    int rank_offset = 0;
    #else
    int     y   = -5 + y_offset;
    int yoffset = ( y *0x20)*2;
    int xoffset = (-3+7+x_offset)*2;
    int name_offset = -1*2;
    int rank_offset = -2*2;
    #endif
    if(v2>0){
        int *ptr = 0x2003CFC;
        do{
            int v4 = CALLT(0x80281D0,v2003C08, v3);
            if(v4){
                int v7;
                CALLT(0x8003608,
                    (value<<6)+ 0x2003D34 + xoffset + yoffset,
                    CALLT(0x8028668,(v7 = CALLT(0x8028170,v2003C08,v3))),
                    0x5000);

                CALLT(0x8004374,
                ptr,
                (value << 6) + 0x2003D3A + xoffset + name_offset + yoffset,
                v1,0,0,
                CALLT(0x8009FA8,geth(
                    CALLT(0x801913C,v7)
                )));
                int v8 = 2;
                if(v4==3){
                    v8 = 4;
                }
                if(v1==4){
                    v8 = 4;
                }
                CALLT(0x8004A14,
                    (value << 6) + 0x2003D46 + xoffset + rank_offset + yoffset,
                    v8,
                    CALLT(0x8028680,v4));
                value += 2;
                ptr += 2;
            }
            ++v3;
        }while(v3<v2);
    }
}

/*
显示成长率
*/
void show_growth(){
    CALLT(0x80890BC,base_info);     //显示基础的文字

    int bouns = 0;          //奖励成长率
    int maxValue = 100;      //最大值设定为25
#define get_growth_bar_len(v) \
    (v)
//#undef show_value_bar
#define show_value_bar_ex(idx,x,y,value,v0,v1) \
    _8089354ex(idx,x,y,(value)>>2,(v0)>>2,(v1)>>2,value)

    int yoffset = 0x20*4;
    u32 char_ptr = get(v2003C08);       //获得角色指针

    //显示力量,魔力的文字
    CALLT(0x8004374,0x2003C2C, 0x2003D6E, 3, 0, 3, CALLT(0x8009FA8,0x48D));
    CALLT(0x8004374,0x2003C7C, 0x2003DEE, 3, 0, 3, CALLT(0x8009FA8,0x48E));
    CALLT(0x8004374,0x2003C7C+8, 0x2003DEE + (0x20*12)*2, 3, 0, 3, CALLT(0x8009FA8,0x478));

    //获得角色

    //力量，技术，速度，运气，守备，魔防
    show_value_bar_ex(0,5,1,
        getb(char_ptr+0x1d)
        ,
    bouns + getb(char_ptr+0x1d),      //没有奖励
    maxValue
    );

    //新加
    //魔力成长率
    show_value_bar_ex(6,5,3,
            //getb(char_ptr+0x1d)
            char_get_magic_growth(getb(char_ptr+4))
        ,
    bouns + char_get_magic_growth(getb(char_ptr+4)),      //没有奖励
    maxValue
    );

    //技术
    show_value_bar_ex(1,5,5,
            getb(char_ptr+0x1E)
        ,
    bouns + getb(char_ptr+0x1e),      //没有奖励
    maxValue
    );

    //速度
    show_value_bar_ex(2,5,7,
            getb(char_ptr+0x1F)
        ,
    bouns + getb(char_ptr+0x1f),      //没有奖励
    maxValue
    );

    //运气
    show_value_bar_ex(3,5,9,
            getb(char_ptr+0x22)
        ,
    bouns + getb(char_ptr+0x22),      //没有奖励
    maxValue
    );

    //守备
    show_value_bar_ex(4,5,11,
            getb(char_ptr+0x20)
        ,
    bouns + getb(char_ptr+0x20),      //没有奖励
    maxValue
    );

    //魔防
    show_value_bar_ex(5,5,13,
            getb(char_ptr+0x21)
        ,
    bouns + getb(char_ptr+0x21),      //没有奖励
    maxValue
    );

    //HP
    show_value_bar_ex(7,5,15,
            getb(char_ptr+28)
        ,
    bouns + getb(char_ptr+28),      //没有奖励
    maxValue
    );
}

/*
设置显示帮助文本
a1 为索引
*/
void JMP808AC2C_r2(int a1,int a2){
    CALLT(0x808BB14,0,-1);
#define v2003C10 *((int*)0x2003C10)
    u32 ptr = 0;
    if(!v2003C10){
        #if CODE_old
        if(a1==1){
            ptr = 0x8A72E58;    //道具
        }
        else if(a1>1){
            ptr = 0x8A72FFC;    //武器熟练度
        }
        else{
            ptr = 0x8A72C7C;    //基本属性
        }
        #else
        //ptr = &sword_cshow;
        //ptr = &char_move;
        if(a1==0){
            ptr = &char_str;
        }
        else if(a1==1){
            ptr = &item0_help;
        }
        else if(a1==2){
            ptr = &sword_cshow;
        }
        else if(a1==3){
            ptr = &char_move;
        }
        else{
            //成长率，未找到显示帮助的文本，只能显示角色信息
            ptr = &char_info9;
        }
        #endif
        v2003C10 = ptr;
    }

    CALLT(0x808B3F0,v2003C10,a2);

#undef v2003C10
}


#endif

#endif
